<?php
error_reporting ( E_ALL ); // all errors
// ror_reporting ( E_ALL ^ E_NOTICE ); // turn on all errors, warnings minus
// notices
//error_reporting ( E_ERROR ); // Errors only


set_time_limit ( 300 ); // 5 Minutes
ob_start ();
$prependFile = '/home/content/50/6934650/html/pear/includes/prepend.php';
if (file_exists ( $prependFile )) {
	include_once $prependFile;
}

require_once ("ConfigParser.php");
require_once ("DBConnection.php");
require_once ("CommandLineHelper.php");
require_once ("LogHelper.php");
abstract class HHAbstract {
	public static $ConfigParser;
	public static $DBConnection;
	public static $CommandLineHelper;
	public static $Logger;
	public $taskID;
	private $ch;
	private $outputContent;
	private $cookieFile;
	private $curlReferer;
	function __construct() {
		$path = dirname ( __FILE__ );
		// $path = '/home/content/50/6934650/html/';
		$onlineMode = false;
		
		if (stripos ( $path, '/home/content/50/6934650/html/' ) !== false) {
			$onlineMode = true;
		}
		if (! defined ( 'ONLINEMODE' )) {
			define ( 'ONLINEMODE', $onlineMode );
		}
		
		if (! isset ( self::$ConfigParser )) {
			self::$ConfigParser = new ConfigParser ( );
		}
		
		if (! isset ( self::$DBConnection )) {
			$this->reconnectDB ();
		}
		
		if (! isset ( self::$CommandLineHelper )) {
			self::$CommandLineHelper = new CommandLineHelper ( self::$DBConnection );
		}
		
		if (! isset ( self::$Logger )) {
			self::$Logger = new LogHelper ( );
		}
		
		if (ONLINEMODE) {
			$this->notifyDBOfTask ();
		}
		$this->cookieFile = realpath ( dirname ( __FILE__ ) ) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR . 'cookie_'.date('Y_m_d_h_i_s').'_'.rand(1,5000).'.txt';

		$this->constructClass ();
		
		if (ONLINEMODE) {
			$this->notifyDBOfTaskFinished ();
		}
	}
	
	function mergeCookiesandDelete(){
		if(isset($this->cookieFile) && file_exists($this->cookieFile)){
			$cookieFileContents = file_get_contents($this->cookieFile);
			if(strlen($cookieFileContents)>0){
				$masterCookieLogFile = realpath ( dirname ( __FILE__ ) ) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR . 'Cookie_Log.txt';
				file_put_contents($masterCookieLogFile, basename($this->cookieFile). ' - Contents ('.date('Y-m-d h:i:s').")\r\n<br>".$cookieFileContents."<hr>\r\n\r\n<br><br>",FILE_APPEND);
			}
			// Delete the cookie contents
			unlink($this->cookieFile);
		}
	}
	
	function __destruct() {
		if (ONLINEMODE) {
			$this->notifyDBOfTaskFinished ();
		}
		$this->getCommandLineHelper ()->__destruct ();
		//$this->getDBConnection ()->__destruct ();
		if (isset ( $this->ch )) {
			curl_close ( $this->ch );
		}
		// Merge the cookie file into the master Cookies file for the given class
		$this->mergeCookiesandDelete();
		
		$this->outputContent = ob_get_contents (); // Capture all the output and
		// display it when class is finished
		ob_end_clean ();
		echo ($this->outputContent);
	}
	function getOutputContent() {
		return $this->outputContent;
	}
	function notifyDBOfTask() {
		// SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
		//$this->getDBConnection()->queryDB("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
		// Turn auto commit off
		//$this->getDBConnection()->queryDB("SET autocommit=0");
		

		//$this->getDBConnection()->queryDB("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");
		// Turn auto commit on
		//$this->getDBConnection()->queryDB("SET autocommit=1");
		

		$query = "insert into task (class,running,started) values ('" . get_class ( $this ) . "',true,now())";
		//$this->getDBConnection()->threadSafeQuery($query,"WRITE");
		$this->getDBConnection ()->queryDB ( $query );
		//$this->getDBConnection()->queryDB("COMMIT;");
		$this->taskID = $this->getDBConnection ()->getDBConnection ()->insert_id;
	}
	function notifyDBOfTaskFinished() {
		// echo ("Notifying DB Task Finished of id: " . $this->taskID . "<br>");
		$query = "update task set running=false where id=" . $this->taskID;
		//$this->getDBConnection()->threadSafeQuery($query,"WRITE");
		$this->getDBConnection ()->queryDB ( $query );
		//$this->getDBConnection()->queryDB("COMMIT;");
		// Turn auto commit on
		//$this->getDBConnection()->queryDB("SET autocommit=1");
		//$this->getDBConnection()->queryDB("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");
	}
	
	function runQuery($query, $con, $returnAffectedRows = false, $retry = 3) {
		$affectedRowCount = 0;
		$results = $this->getDBConnection ()->queryCon ( $query, $con );
		$affectedRowCount = $con->affected_rows;
		if ($con->errno) {
			if ($retry > 0 && $con->errno == 2006) {
				//sleep(10 + rand(0, 15));
				if (! $con->ping ()) {
					$this->reconnectDB ();
					$con = $this->getDBConnection ()->getMatchingCon ( $con );
				}
				return $this->runQuery ( $query, $con, $returnAffectedRows, -- $retry );
			
			} else {
				$this->getLogger ()->log ( 'Couldnt execute query: ' . $query . '<br>Mysql Error (' . $con->errno . '): ' . $con->error . " | Retries: " . (3 - $retry), PEAR_LOG_ERR );
			}
		}
		if ($returnAffectedRows) {
			return $affectedRowCount;
		} else {
			return $results;
		}
	}
	
	function reconnectCon($con, $tries = 3) {
		// Check if connection is open and return if you can reconnect
		if ($con->ping ()) {
			return $con;
		} else {
			// Get the tread ID
			$threadID = $con->thread_id;
			// Find out which connection it is and reset it then return it
			if ($this->getDBConnection ()->getDBConnection ()->thread_id == $threadID) {
			
			}
		}
	}
	
	function reconnectDB() {
		if (ONLINEMODE) {
			self::$DBConnection = new DBConnection ( mysqlServerIP2, dbname, dbuser, dbpassword );
		} else {
			self::$DBConnection = new DBConnection ( localmysqlServerIP2, localdbname, localdbuser, localdbpassword );
		}
	}
	static function getConfigParser() {
		return self::$ConfigParser;
	}
	static function getCommandLineHelper() {
		return self::$CommandLineHelper;
	}
	static function getDBConnection() {
		return self::$DBConnection;
	}
	static function getLogger() {
		return self::$Logger;
	}
	function __toString() {
		$classVars = get_class_vars ( get_class ( $this ) );
		$vars = '';
		foreach ( $classVars as $name => $value ) {
			$value = $this->$name;
			if (is_array ( $value )) {
				$value = implode ( ",", $value );
			}
			$vars .= "<b>$name</b> : $value\n<br>";
		}
		return $vars;
	}
	abstract function constructClass();
	
	function getUrlAsLink($url, $display = null) {
		if (! isset ( $display )) {
			$display = $url;
		}
		return '<a href="' . $url . '">' . $display . '</a>';
	}
	
	function setCookieFile($fileName){
		$this->mergeCookiesandDelete();
		$this->cookieFile = realpath ( dirname ( __FILE__ ) ) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR . $fileName;
		file_put_contents($this->cookieFile, '');
		chmod($this->cookieFile, 0755);
	}
	
	function get_web_page($url, $newSession = false, array $additionalOptions = null) {
		// This example request includes an optional API key which you will need to
		// remove or replace with your own key.
		// Read more about why it's useful to have an API key.
		// The request also includes the userip parameter which provides the end
		// user's IP address. Doing so will help distinguish this legitimate
		// server-side traffic from traffic which doesn't come from an end-user.
		// sendRequest
		// note how referer is set manually
		$certPath = realpath ( dirname ( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'cacert.pem';
		
		$urlParts = parse_url($url);
		$referer = $urlParts['host'];
		
		if(!isset($this->curlReferer)){
			$this->curlReferer = $referer;
		}
		
		$options = array (
		CURLOPT_URL => $url, 
		CURLOPT_RETURNTRANSFER => true, // return web page
		CURLOPT_FOLLOWLOCATION => true, // follow redirects
		CURLOPT_ENCODING => "", // handle all encodings
		CURLOPT_REFERER => $this->curlReferer, // set referer on redirect
		CURLOPT_CONNECTTIMEOUT => 240, // timeout on connect
		CURLOPT_TIMEOUT => 240, // timeout on response
		CURLOPT_MAXREDIRS => 20, 
		CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/4', 
		CURLOPT_BUFFERSIZE => (1024 * 1024 * 512), 
		CURLOPT_SSL_VERIFYPEER => true, 
		CURLOPT_CAINFO => $certPath, 
		//CURLINFO_HEADER_OUT => true, // enable tracking of headers
		CURLOPT_COOKIESESSION => true,
		CURLOPT_COOKIEFILE => $this->cookieFile,
		CURLOPT_COOKIEJAR =>  $this->cookieFile,
		);
		
		if ($newSession === true || ! isset ( $this->ch )) {
			$this->setCookieFile(basename($this->cookieFile));
			if (! file_exists($this->cookieFile) || ! is_writable($this->cookieFile))
			{
			    echo '<b>Cookie file missing or not writable.</b><br>';
			}
			$this->ch = curl_init ();
			$this->curlReferer = null;
		}else{
			$this->curlReferer = $url;
		}
		
		if (isset ( $additionalOptions ) && count ( $additionalOptions ) > 0) {
			foreach ( $additionalOptions as $index => $key ) {
				$options [$index] = $key;
			}
		}
		
		//var_dump($options);
		//echo('<br><br>');
		
		curl_setopt_array ( $this->ch, $options );
		$body = curl_exec ( $this->ch );
		
  		// Note: CURLINFO_HEADER_OUT must be turned on
		//echo('<br>Request Headers:<br>');
  		//var_dump(curl_getinfo($this->ch, CURLINFO_HEADER_OUT)); 
  		//echo('<br><br>');
		
		
		if($body===false){
			echo("Curl Error (".curl_errno($this->ch)."):  ".curl_error($this->ch).'<br>');
		}
		
		return $body;
	}
}
?>

